package com.mobile.tools;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.SimpleValue;

import com.mobile.dao.HibernateSessionFactory;
import com.mobile.tools.cfg.SessionFactoryUtil;
import com.mobile.tools.exception.FileIsExistsException;
import com.mobile.tools.exception.FilePathException;
/**
 * 根据hibernate中configration的实体管理字段(增加或删除)
 * @author hf
 *
 */
public class HibernateEntityManager {
	//配置文件名
	private String configName;
	//hbm.xml配置文件中动态属性名
	private Component entityProperties;
	//实体类
	private Class entityClass;
	//实体名称
	private String entityName;
	//动态组件名称
	private String componentName;
	//映射文件名
	private String mappingName;
	//映射文件路径
	private String hbmXmlPath;
	//实体类
	private PersistentClass persistentClass;
	//sessionFactory的spring工具类
	private SessionFactoryUtil sessionFactoryUtil;
	//映射文件处理类
	private HibernateMappingManager hibernateMappingManager;
	//配置文件与pojo的相对路径
	private String hbmToPojoPath="xml/";
	
	public void setHibernateMappingManager(
			HibernateMappingManager hibernateMappingManager) {
		this.hibernateMappingManager = hibernateMappingManager;
	}
	public void setSessionFactoryUtil(SessionFactoryUtil sessionFactoryUtil) {
		this.sessionFactoryUtil = sessionFactoryUtil;
	}
	public HibernateEntityManager(){
		super();
	}
	public HibernateEntityManager(String entityName, String componentName,
			String mappingName, String hbmXmlPath) {
		super();
		this.entityName = entityName;
		this.componentName = componentName;
		this.mappingName = mappingName;
		this.hbmXmlPath = hbmXmlPath;
		this.persistentClass = this.sessionFactoryUtil
									.getClassMapping(entityName);
	}
	public void setPersistentClass(PersistentClass persistentClass) {
		this.persistentClass = persistentClass;
	}
	public String getMappingName() {
		return mappingName;
	}
	public void setMappingName(String mappingName) {
		this.mappingName = mappingName;
	}
	/**
	 * 构造函数
	 * @param entityName
	 * @param componentName
	 * @param mappingName
	 */
	public HibernateEntityManager(String entityName,String componentName,String mappingName){
		this.entityName=entityName;
		this.componentName=componentName;
		this.mappingName=mappingName;
		this.persistentClass=this.sessionFactoryUtil.getClassMapping(entityName);
		this.hbmXmlPath = this.persistentClass
								.getClass()
								.getResource(this.mappingName)
								.getPath();
	}
	/**
	 * 构造函数
	 * @param entityClass
	 * @param componentName
	 * @param mappingName
	 */
	public HibernateEntityManager(Class entityClass,String componentName,String mappingName){
		this.entityClass=entityClass;
		this.componentName=componentName;
		this.mappingName=mappingName;
		this.persistentClass=this.sessionFactoryUtil.getClassMapping(entityClass.getName());
		this.hbmXmlPath = this.persistentClass
								.getClass()
								.getResource(this.mappingName)
								.getPath();
	}
	/**
	 *  获得hibernate的组建
	 * @return
	 */
	public Component getEntityProperties(){
		if(this.entityProperties==null){
			Property property=this.persistentClass.getProperty(componentName);
			this.entityProperties=(Component)property.getValue();
		}
		return this.entityProperties;
	}
	/**
	 * 创建新的表
	 * @param newEntityName
	 */
	public void createEntity(String newEntityName,String newHbmName,Collection<FieldInfo> collection)
			throws FilePathException,FileIsExistsException {
		Class clazz = HibernateSessionFactory.getClassMapping(entityName)
				.getMappedClass();
		String className = HibernateSessionFactory.getClassMapping(entityName)
				.getClassName();
		className = className.substring(className.lastIndexOf(".") + 1).concat(
				".class");
		String filePath = clazz.getResource(className).getPath();

		filePath = filePath.replace(className, hbmToPojoPath+ mappingName);

		/* ehd.setHem(htm); */

		HibernateMappingManager hmm = new HibernateMappingManager();

		// 创建mapping文件
		CopyFile.copyFile(newHbmName, filePath);

		filePath = filePath.replace(mappingName, newHbmName);

		// 修改新的配置文件在hibernate的config的名称
		hmm.updateEntityName(filePath, newEntityName);
		
		this.addEntityField(collection);
		// 把新添加爱的model添加到hibernate的config中
		//HibernateSessionFactory.getConfiguration().addFile(filePath);
		// 修改hibernate 的配置文件
		String filePathClass = filePath
				.substring(filePath.indexOf("classes/") + 8);
		
		hmm.updateHibernateConfig(configName, newHbmName, filePathClass);
		
		this.addEntityField(collection);
		// 添加属性
		/*HibernateEntityManager htm = new HibernateEntityManager(newEntityName,
				componentName, newHbmName, filePath);*/
		//this.addEntityField(collection);
		// 重新加载hibernate的配置文件
		HibernateSessionFactory.rebuildSessionFactory();
	}
	/**
	 * 添加字段
	 * @param name			添加的字段
	 * @param type			字段的类型
	 */
	public void addEntityField(String name,Class type){
		SimpleValue simpleValue=new SimpleValue();
		simpleValue.addColumn(new Column(name));
		simpleValue.setTypeName(type.getName());
		
		simpleValue.setTable(this.persistentClass.getTable());
		
		Property property=new Property();
		property.setName(name);
		property.setValue(simpleValue);
		getEntityProperties().addProperty(property);
		
		updateMapping();
	}
	/**
	 * 添加多个字段
	 * @param list
	 */
	public void addEntityField(List<FieldInfo> list){
		for (FieldInfo fi:list) {
			addEntityField(fi);
		}
		updateMapping();
	}
	/**
	 * 添加多个字段
	 * @param list
	 */
	public void addEntityField(Collection<FieldInfo> collection){
		for(FieldInfo fi:collection){
			addEntityField(fi);
		}
		updateMapping();
	}
	/**
	 * 添加实体映射的字段
	 * @param fi		字段类
	 */
	private void addEntityField(FieldInfo fi){
		String fieldName=fi.getFieldName();
		String fieldType=fi.getFieldType().getName();
		
		SimpleValue simpleValue = new SimpleValue();
		simpleValue.addColumn(new Column(fieldName));
		simpleValue.setTypeName(fieldType);
		
		simpleValue.setTable(this.persistentClass.getTable());
		Property property = new Property();
		property.setName(fieldName);
		property.setValue(simpleValue);
		getEntityProperties().addProperty(property);
	}
	/**
	 * 删除字段
	 * @param name			字段名称
	 */
	public void removeEntityField(String name){
		Iterator<Property> propertyIterator=getEntityProperties().getPropertyIterator();
		
		while(propertyIterator.hasNext()){
			Property property=propertyIterator.next();
			if(property.getName().equals(name)){
				propertyIterator.remove();
				updateMapping();
				return;
			}
		}
	}
	//更新实体的修改到配置文件中
	private synchronized void updateMapping(){
		this.hibernateMappingManager.updateClassMapping(this);
		/*String filePathClass=this.hbmXmlPath.substring(this.hbmXmlPath.indexOf("classes/")+8);
		this.hibernateMappingManager.updateHibernateConfig(this.configName,this.newMappingName, filePathClass);*/
	}
	public PersistentClass getPersistentClass(){
		return this.persistentClass;
	}
	
	
	
	public String getEntityName() {
		return entityName;
	}
	public void setEntityName(String entityName) {
		this.entityName = entityName;
	}
	public void setEntityProperties(Component entityProperties) {
		this.entityProperties = entityProperties;
	}
	public Class getEntityClass() {
		return entityClass;
	}
	public void setEntityClass(Class entityClass) {
		this.entityClass = entityClass;
	}	
	public String getComponentName() {
		return componentName;
	}
	public void setComponentName(String componentName) {
		this.componentName = componentName;
	}
	public String getHbmXmlPath() {
		return hbmXmlPath;
	}
	public void setHbmXmlPath(String hbmXmlPath) {
		this.hbmXmlPath = hbmXmlPath;
	}
	public void setConfigName(String configName) {
		this.configName = configName;
	}
}
